﻿//

using System;
using System.Collections.Generic;
using System.Web;
using DotNetWikiBot;
using System.Threading;
using System.Collections;
using System.IO;
using System.Text;


namespace wikibot
{

    class Program
    {
        bool OK = true;
        public static System.Text.RegularExpressions.Regex heading = new System.Text.RegularExpressions.Regex("\\s*==.*==");
        public static System.Text.RegularExpressions.Regex ts = new System.Text.RegularExpressions.Regex("[0-9][0-9]\\:[0-9][0-9]\\,\\s");
        

        public static class Logger
        {
            private static bool Locked = false;
            public static List<string> messages = new List<string>();
            public static void Insert(string data) 
            {
                while (Locked)
                {
                    Thread.Sleep(100);
                }
                messages.Add(data);
            }
            public static void start()
            {
                while (Config.OK)
                {
                    Locked = true;
                    if (messages.Count > 0)
                    {
                        foreach (string text in messages)
                        {
                            System.IO.File.AppendAllText(Config.LogPath, text);
                        }
                    }
                    messages.Clear();
                    Locked = false;
                    Thread.Sleep(2000);
                }
            }
        }

        public class t
        {
            public static int counter = 0;
            public static string config;
            public DotNetWikiBot.Site testwp; // test.wikipedia.org
            public DotNetWikiBot.Site dewiki;
            public DotNetWikiBot.Site meta;
            public DotNetWikiBot.Site co;
            public DotNetWikiBot.Site enwiki;
            public static List<string> skip = new List<string>();
            public bool active;
            public static bool increment()
            {
                counter++;
                if (counter > 200)
                {
                    Config.OK = false;
                    return false;
                }
                return true;
            }
            public t()
            {
                active = false;
            }


            public static class Parser
            {
                public static string getconf(string key, string text)
                {
                    string return_value = "";
                    if (text.Contains(key))
                    {
                        return_value = text.Substring(text.IndexOf(key), text.IndexOf(';', text.IndexOf(key)) - text.IndexOf(key));
                        return_value = return_value.Replace(key, "");
                        return return_value;
                    }
                        return "";
                }

                public static bool IgnoredPage(string text)
                {
                        return System.Text.RegularExpressions.Regex.IsMatch(text, @"\{\{(nobots|bots\|(allow=none|deny=(?!none).*(SharedIPArchive.*@|all)|optout=all))\}\}", System.Text.RegularExpressions.RegexOptions.IgnoreCase);;
                }

                public static string ParseTemplateByText(string page, string text)
                {
                    string return_value = "";
                    if (page.Contains(text))
                    {
                        int a = page.IndexOf(text);
                        //try to get a beginning of template
                        System.Text.RegularExpressions.MatchCollection rs;
                        rs = heading.Matches(page);
                        int b = -10;
                        if (rs.Count == 0)
                        {
                            int d = a;
                            while (page.Substring(d, 2) != "\n\n" || d < 1)
                            {
                                d--;
                            }

                            if (d > 1)
                            {
                                d = d + 2;
                                b = d;
                            }
                        }
                        else
                        {
                            foreach (System.Text.RegularExpressions.Match x in rs)
                            {
                                if (b < x.Index && x.Index < a)
                                {
                                    b = x.Index;
                                }
                            }
                        }
                        
                        // we didn't
                        if (b == -10)
                        {
                            return "";
                        }

                        // now we need to get the end
                        int c = page.IndexOf("==", a);
                        if (c > b)
                        {
                            return_value = page.Substring(b, c - b);
                        }
                        else
                        {
                            return_value = page.Substring(b);
                        }
                        if (return_value.Contains(text))
                        {
                            return return_value;
                        }
                    }
                    return "";
                }
            }

            public static int Log(String message)
            {
                try
                {
                    message = "SYSTEM: " + message;
                    Console.WriteLine(message);
                    message = DateTime.Now + "  " + message;
                    message = "<tr><td>" + message + "</td></tr>\n";
                    Logger.Insert(message);
                }
                catch (Exception b)
                {
                    Console.WriteLine("yay" + b.Message);
                }
                return 0;
            }

            public static bool TLog(int id, String message)
            {
                try
                {
                    message = message.Insert(0, DateTime.Now + " - TASK: ");
                    message = "<tr><td>" + message + "</td></tr>\n";
                    Logger.Insert(message);
                }
                catch (Exception b)
                {
                    Console.WriteLine("yay" + b.Message);
                }
                return false;
            }
            public virtual int Do()
            {
                TLog(1, "error: nothing to do");
                return 1;
            }

            public bool LogP(String message)
            { // private logs
                Console.WriteLine(message);
                return true;
            }

            public virtual void Init()
            {
            }
        }

        public static class ArchivingSystem
        {
            public class ArchiveObject
            {
                public bool ok = false;
                public int parts = 0;
                public List<string> page = new List<string>();
                public ArchiveObject(string text)
                {
                    if (text.Length < Config.size)
                    {
                        page.Add(text);
                        ok = true;
                        parts = 1;
                    }
                    else
                    {
                        parts++;
                        ok = false;
                    }
                }
            }
            private static string GetTemplates(string text)
            {
                return "";
            }
            /// <summary>
            /// Archive page
            /// </summary>

            public static string CheckBlock(string text)
            {
                foreach (string template in task_block.tlist)
                { 
                    if (text.Contains(template))
                    {
                        return template;
                    }
                }
                return "";
            }

            public static string ArchiveFull(DotNetWikiBot.Page pagename, string ip, DotNetWikiBot.Site wiki)
            {
                string an;
                int n = 1;
                bool changed = false;
                bool archived = false;
                string backup = pagename.text;
                
                try
                {
                    string text = "";
                    bool broken = true;

                    foreach (System.Text.RegularExpressions.Regex re in Config.listk)
                    {
                        if (re.Match(pagename.text).Success)
                        {
                            text = text + re.Match(pagename.text).Value + "\n";
                            pagename.text = re.Replace(pagename.text, "");
                            broken = false;
                        }
                    }

                    if (pagename.text.Replace(" ", "").Replace("\n", "") == "")
                    {
                        broken = true;
                    }

                    if (broken)
                    {
                        pagename.text = backup;
                        return "";
                    }

                    if (Config.NA)
                    {
                        n = 1;
                        DotNetWikiBot.Page ac = new Page(wiki, pagename.title + "/Archive");
                        ac.Load();
                        if (ac.Exists())
                        {
                            an = pagename.title + "/Archive";
                            
                        }
                        else
                        {
                            ac = new Page(wiki, pagename.title + "/Archive");
                            ac.Load();
                            if (ac.Exists())
                            {
                                t.Log("Error existing Archive");
                                string token;
                                token = wiki.GetPageHTM(wiki.indexPath + "api.php?action=query&titles=" + HttpUtility.UrlEncode(ac.title) + "&format=xml&prop=info&intoken=move");
                                token = System.Text.RegularExpressions.Regex.Match(token, "movetoken=\\\".*\\\"").Value;
                                token = token.Replace("movetoken=", "");
                                token = token.Replace("\"", "");
                                wiki.PostDataAndGetResultHTM(wiki.indexPath + "api.php?action=move", "from=" + HttpUtility.UrlEncode(pagename.title + "/Archive") + "&to=" + HttpUtility.UrlEncode(pagename.title + "/Archive_1") + "&token=" + System.Web.HttpUtility.UrlEncode(token) + "&reason=" + System.Web.HttpUtility.UrlEncode("Moving archive to correct name "));
                                an = pagename.title + "/Archive_1";
                            }
                            else
                            {
                                an = pagename.title + "/Archive_" + n.ToString();
                                ac = new Page(wiki, an);
                                ac.Load();
                                while (ac.Exists())
                                {
                                    n++;
                                    an = pagename.title + "/Archive_" + n.ToString();
                                    ac = new Page(wiki, an);
                                    ac.Load();
                                }
                            }
                        }
                        an = pagename.title + "/Archive_" + n.ToString();
                    }
                    else
                    {
                        an = pagename.title + "/Archive";
                    }
                    DotNetWikiBot.Page ar = new Page(wiki, an);
                    ar.Load();
                    t.TLog(0, "Page: " + pagename.title + " archiving to: " + an);
                    string archive_text;
                    
                    

                    foreach (System.Text.RegularExpressions.Regex re in Config.listc)
                    {
                        pagename.text = re.Replace(pagename.text, "");
                    }
                    
                    archive_text = "";

                    

                        changed = true;
                        if (text.Contains("{{archive box") != true)
                        {
                            text = SetHeader(text, ar, ip);
                        }
                        if (ar.text.Contains("{{talkarchive") != true)
                        {
                            ar.text = "{{talkarchive}}\n\n" + ar.text;
                        }
                            archive_text = pagename.text;
                            pagename.text = text;

                        ar.text = ar.text + "\n" + archive_text;

                        
                        //pagename.text = pagename.text.Replace(templates, ""); 
                    string message = CheckBlock(pagename.text);
                    if (message == "")
                    {
                        t.Log("Page doesn't contain template to remove");
                    }
                    else
                    {
                        changed = true;
                        while (message != "")
                        {

                            t.Log("Removing template");
                            string template = message;
                            pagename.text = pagename.text.Replace(template, "");
                            ar.text = ar.text + template + "\n\n";
                            message = CheckBlock(pagename.text);
                        }
                    }
                    if (changed)
                    {
                        foreach (System.Text.RegularExpressions.Regex list in Config.listk)
                        {
                            if (list.Match(ar.text).Success)
                            {
                                string template = list.Match(ar.text).Value;
                                pagename.text = template + " \n" + pagename.text;
                                ar.text = ar.text.Replace(template, "");
                            }
                        }
                        ArchiveObject page = new ArchiveObject(ar.text);
                        if (page.ok)
                        {
                            if (!Config.NA)
                            {
                                ar.Save(ar.text, Config._summary1, true);
                                t.TLog(0, "Page: " + pagename.title + " archived to: " + an);
                            }
                            else
                            {
                                int i = n;
                                foreach (string data in page.page)
                                {
                                    Page archive = new Page(wiki, pagename.title + "/Archive_" + i.ToString());
                                    archive.Load();
                                    if (archive.Exists())
                                    {
                                        t.Log("Fatal, inconsistent archive n" + i.ToString());
                                        break;
                                    }
                                    archive.Save(data, Config._summary1.Replace("$page", "[[" + archive.title + "]]"), true);
                                    t.TLog(0, "Page: " + pagename.title + " archived to: " + archive.title);
                                    i++;
                                    archived = true;
                                }
                            }
                        }
                        else
                        {
                            t.Log("Unable to archive page!");
                            pagename.text = backup;
                            return "";
                        }
                        if (archived == true)
                        {
                            return pagename.text;
                        }
                            pagename.text = backup;
                            return "";
                    }
                }
                catch (Exception errorm)
                {
                    t.Log("Exception when archiving page: " + errorm.Message);
                    pagename.text = backup;
                    return "";
                }
                return "";
            }

            /// <summary>
            /// Create header
            /// </summary>
            public static string SetHeader(string text, Page archive, string ip)
            {
                text = "{{archive box|auto=yes}}\n " + text;

                return text;
            }
        }

        public static class BlockCache
        {
            public static int offset = 400;
            public class Block
            {
                public double Time;
                public string IP;
                
                public virtual bool IsTimed
                {
                    get { return (Time == 0); }
                }

                public Block(double time, string ip)
                {
                    IP = ip;
                    Time = time;
                    
                }
            }
            public static List<Block> blocks = new List<Block>();
            public static List<Block> _blocks = new List<Block>();

            public static bool IsExpired(double time)
            {
                double current = double.Parse(DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString());
                if (time < current)
                {
                    return true;
                }
                return false;
            }

            public static bool IsBlocked(string name)
            {
                try
                {
                    foreach (Block us in _blocks)
                    {
                        if (name == us.IP)
                        {
                            if (!IsExpired(us.Time))
                            {
                                return true;
                            }
                            else
                            {
                                return false;
                            }
                        }
                    }
                    string result;
                    result = PBot.enwiki.PostDataAndGetResultHTM("/w/api.php", "action=query&list=blocks&format=xml&bkprop=id|user|by|timestamp|expiry|reason|range|flags&bklimit=3&bkip=" + System.Web.HttpUtility.UrlEncode(name));
                    if (result.Contains("block id"))
                    {
                        return true;
                    }
                    return false;
                }
                catch (Exception errorm)
                {
                    t.Log("Exception when checking: " + errorm.Message);
                    return true;
                }
            }

            public static double _ln(double time)
            {
                double current = double.Parse(DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString());
                return time - current;
            }

            public static void Regenerate()
            {
                Clear();
                Create();
            }

            public static void Clear()
            {
                blocks = new List<Block>();
            }

            public static void Create()
            {
                string[] db = System.IO.File.ReadAllLines("db");
                foreach (string x in db)
                { 
                    string[] val = x.Split('|');
                    if (val[0] == "infinity") val[0] = "0";
                     blocks.Add(new Block(double.Parse(val[0]), val[1]));
                }
            }
        }

        public class task_block : t
        { //every task should be inherited from base
            public static string[] templatelist;
            public static string[] tlist;

            private bool Load()
            {
                return true;
            }

            public static string Match(string text)
            {
                foreach (string template in templatelist)
                {
                    if (text.Contains(template))
                    {
                        return template;
                    }
                }
                return "";
            }

            public override int Do()
            {
                BlockCache.Create();
                while (true)
                {
                    // we need to remove the block message if there
                    foreach (BlockCache.Block block in BlockCache.blocks)
                    {
                        if (BlockCache.IsExpired(block.Time))
                        {
                            block.Time = BlockCache.offset + block.Time;
                            BlockCache._blocks.Add(block);
                        }
                    }
                    foreach (BlockCache.Block block in BlockCache._blocks)
                    {
                        if (BlockCache.IsExpired(block.Time))
                        {
                            Log("User has expired block: " + block.IP);
                            // we need to remove the block message if there
                            DotNetWikiBot.Page sb = new Page(testwp, "User talk:" + block.IP);
                            sb.Load();
                            string message = (Match(sb.text));
                            if (message == "")
                            {
                                Log("Page doesn't contain template to remove");
                            }
                            else
                            {
                                Log("Removing template");
                                string template = t.Parser.ParseTemplateByText(sb.text, message);
                                if (template != "")
                                {
                                    sb.text = sb.text.Replace(template, "");
                                    sb.Save(sb.text, Config._summary2, true);
                                }
                            }
                        }
                    }
                    Thread.Sleep(800000);
                    
                }
            }
        };

        public class task_10 : t
        {
            public int Do()
            {
                System.IO.StreamReader s = System.IO.File.OpenText("list");
                string person = "";
                string archive;
                while (s.EndOfStream != true)
                {
                    person = s.ReadLine();
                    Page xx = new DotNetWikiBot.Page(enwiki, person);
                    xx.Load();
                    if (!(xx.text.Contains("{{Shared") || xx.text.Contains("{{mobi") || xx.text.Contains("{{Si") || xx.text.Contains("{{vandali") || xx.text.Contains("{{Dynamic") || xx.text.Contains("{{isp") || xx.text.Contains("{{shared") || xx.text.Contains("{{ISP")))
                    {
                        System.IO.File.AppendAllText("fl", person + "\n");
                    }
                }
                return 0;
            }
        }

        public class task_6 : t
        {
            public override int Do()
            {
                
                DotNetWikiBot.Page co = new DotNetWikiBot.Page(enwiki, "Special:MyPage/Config");
                co.Load();
                if (co.text != t.config)
                {
                    t.Log("Reloading configuration");
                    PBot.Load();
                }
                return 0;
            }
        }
        public class task_2 : t
        {
            public int Check()
            {
                DotNetWikiBot.Page shut = new DotNetWikiBot.Page(enwiki, "Special:MyPage/Shutdown");
                shut.Load();
                if (shut.text.Contains("if you want to shutdown this bot change this to the shutdown reason and bot will be terminated") == false)
                {
                    Log("Terminated with: " + shut.text);
                    active = false;
                    Config.OK = false;
                }
                return 2;
            }

            public int Do()
            {
                Check();
                String s = "";

                if (active == false)
                {
                    Config.OK = false;
                }
                Thread.Sleep(12000);
                return 0;
            }
            public void Init()
            {
                TLog(2, "Loading task #2");
                active = true;
            }

        };



        public class task_4 : t
        { //example task
            public void Init()
            {
                TLog(4, "Initialising task 4");
                active = true;
                TLog(4, "OK");
            }

            private bool BlockOk(string user)
            {
                user = "User:" + user;
                string query = PBot.enwiki.PostDataAndGetResultHTM("/w/api.php", "action=query&list=logevents&format=xml&letype=block&lelimit=2&letitle=" + System.Web.HttpUtility.UrlEncode(user));
                if (query.Contains("action=\"block"))
                {
                    query = query.Substring(query.IndexOf("expiry"), 28);
                    query = query.Replace("expiry=\"", "");
                    DateTime bt = DateTime.Parse(query).AddSeconds(BlockCache.offset);
                    if (bt < DateTime.Now)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                return true;
            }

            private bool MatchedTime(string user)
            {
                try
                {
                    string query = PBot.enwiki.PostDataAndGetResultHTM("/w/api.php", "action=query&titles=" + System.Web.HttpUtility.UrlEncode(user) + "&prop=info" + "&format=xml");
                    string x = query.Substring(query.IndexOf("touched"), 28);
                    x = x.Replace("touched=\"", "");
                    //x = x.Replace("\"", "");
                    DateTime time;
                    if (DateTime.TryParse(x, out time))
                    {
                        time = DateTime.Parse(x);
                        if (time < Config.ExpiryDate)
                        {
                            return true;
                        }
                    }
                }
                catch (Exception errorm)
                {
                    t.Log("Exception: " + errorm.Message);
                }
                return false;
            }

            public int Do()
            {
                System.IO.StreamReader s = System.IO.File.OpenText("bb");
                string person = "";
                    PageList tl = new PageList(enwiki);
                    tl.FillFromCategory("Category:Wikipedia_user_talk_pages_of_shared_IP_addresses");
                    bool cleaned = false;
                    string archive;
                    foreach (Page sb in tl)
                    {
                        try
                        {
                        person = sb.title;
                        if (person.Contains("Archive"))
                        {
                            continue;
                        }
                        sb.Load();
                        string orig = sb.text;
                        cleaned = false;
                        // get all threads

                        

                        string text = "";

                        if (t.Parser.IgnoredPage(sb.text))
                        {
                            continue;
                        }

                        // template list
                        sb.text = sb.text.Replace("{{Whois|", "{{Whois test|");
                        sb.text = sb.text.Replace("{{Static IP|", "{{Static IP test|");
                        sb.text = sb.text.Replace("{{Shared IP|", "{{Shared IP test|");
                        sb.text = sb.text.Replace("{{ISP|", "{{ISP test|");
                        sb.text = sb.text.Replace("{{Shared IP address (public)|", "{{Shared IP address (public) test|");
                        sb.text = sb.text.Replace("{{Dynamic IP|", "{{Dynamic IP test|");
                        sb.text = sb.text.Replace("{{Mobile IP|", "{{Mobile IP test|");
                        sb.text = sb.text.Replace("{{Shared IP corp|", "{{Shared IP corp test|");
                        sb.text = sb.text.Replace("{{Shared IP edu|", "{{Shared IP edu test|");
                        sb.text = sb.text.Replace("{{Shared IP gov|", "{{Shared IP gov test|");
                        sb.text = sb.text.Replace("{{SingNet|", "{{SingNet test|");

                        bool stop = false;

                        foreach (string c in t.skip)
                        { 
                            if (sb.text.Contains(c))
                            {
                                stop = true;
                            }
                        }

                        if (stop)
                        {
                            t.Log("Skipped page");
                            continue;
                        }
                        string backup = sb.text;
                        Log("Checking if page can be archived");
                        if (MatchedTime(person))
                        {
                            if (!BlockCache.IsBlocked(person.Replace("User talk:", "").Replace("User_talk:", "")))
                            {
                                if (BlockOk(person.Replace("User_talk:", "").Replace("User talk:", "")))
                                {
                                    Log("Archiving page " + person);
                                    string archived_text = ArchivingSystem.ArchiveFull(sb, person, enwiki);
                                    sb.text = backup;
                                    if (archived_text != "")
                                    {
                                        sb.text = archived_text;
                                        cleaned = true;
                                    }
                                }

                            }
                            //string message = t.Parser.ParseTemplateByText(expired, sb.text);
                            //if (message != "")

                            // remove blocked template
                            //sb.text.Replace(message, "");

                        }

                        if (sb.text != orig && sb.text != null && sb.text != "")
                        {
                            string summary;
                            if (cleaned == false)
                            {
                                summary = Config._summary2;
                                summary = Config.summary_half;
                            }
                            else
                            {
                                summary = Config._summary2;
                            }
                            sb.Save(sb.text, summary, true);
                            t.increment();
                            System.Threading.Thread.Sleep(8000);
                        }
                        Log(person);
                        
                    }
                        catch (Exception errorm)
                        {
                            t.Log("Exception when processing page: " + errorm.Message);
                        }
                }
                
                return 0;
            }
        };


        public class PBot : Bot
        {
            public String login = Config.username;
            public String pw = "";
            public bool started;
            public static DotNetWikiBot.Site testwp;
            public static DotNetWikiBot.Site dewiki;
            public static DotNetWikiBot.Site meta;
            public static DotNetWikiBot.Site commons;
            public static DotNetWikiBot.Site enwiki;
            public static DotNetWikiBot.Site cswiki;
            public System.Threading.Thread t6;
            public System.Threading.Thread t1;
            public System.Threading.Thread t10;
            public System.Threading.Thread t2;
            public System.Threading.Thread t4;
            public task_block job_x1;
            public task_2 job_x2;
            public task_4 job_x4;
            public task_6 job_x6;
            public task_10 job_x10;

            public int Log(String message)
            {
                t.Log(message);
                return 0;
            }

            public bool TLog(int id, String message)
            {
                t.TLog(0, message);
                return false;
            }

            public void d1()
            {
                while (Config.OK == true)
                {
                    job_x1.Do();
                    Thread.Sleep(500000);
                }
            }
            public void d2()
            {
                while (Config.OK == true)
                {
                    job_x2.Do();
                }
            }
            public void d4()
            {
                while (Config.OK == true)
                {
                    job_x4.Do();
                }
            }
            public void d10()
            {
               
                    job_x10.Do();
            }
            public void d6()
            {
                while (Config.OK)
                {
                    job_x6.Do();
                    Thread.Sleep(32000);
                }
            }


            public static void Load()
            {
                t.Log("Loading config");
                Page cf = new Page(enwiki, "User:SharedIPArchiveBot/Config");
                cf.Load();
                string date = t.Parser.getconf("archive-time=", cf.text);
                if (date.Contains("d"))
                {
                    Config.ExpiryDate = DateTime.Now;
                    Config.ExpiryDate = Config.ExpiryDate.AddDays(double.Parse(date.Substring(0, date.IndexOf("d"))) * -1 );
                }
                BlockCache.offset = int.Parse(t.Parser.getconf("delay=", cf.text));
                Config._summary1 = t.Parser.getconf("summary1=", cf.text);
                Config._summary2 = t.Parser.getconf("summary2=", cf.text);
                Config.summary_half = t.Parser.getconf("summaryhalf=", cf.text);
                t.config = cf.text;
                Config.listc.Clear();
                foreach (string x in t.Parser.getconf("cleanuplist=", cf.text).Replace("\n", "").Split(','))
                { 
                    Config.listc.Add(new System.Text.RegularExpressions.Regex(x));
                }
                Config.listk.Clear();
                t.skip.Clear();
                foreach (string x in t.Parser.getconf("skiplist=", cf.text).Replace("\n", "").Split(','))
                {
                    t.skip.Add(x);
                }
                foreach (string x in t.Parser.getconf("statictlist=", cf.text).Replace("\n", "").Split(','))
                {
                    Config.listk.Add(new System.Text.RegularExpressions.Regex(x));
                }
                task_block.templatelist = t.Parser.getconf("templatelist=", cf.text).Replace("\n", "").Split(',');
                task_block.tlist = t.Parser.getconf("templateblockslist=", cf.text).Replace("\n", "").Split(',');
                Config.replace = bool.Parse(t.Parser.getconf("replace-blocked=", cf.text));
                t.Log("Reloaded ok");
            }

            public void Initialise()
            {
                Log("Started wikibot core version 1.0, timeout disabled");
                Log("Connecting to english wp...");
                enwiki = new Site("en.wikipedia.org", Config.username, Config.password);
                testwp = new Site("test.wikipedia.org", Config.username, Config.password);
                Log("Tasks...");
                Load();
                job_x1 = new task_block();
                job_x1.enwiki = enwiki;
                job_x1.testwp = testwp;
                job_x10 = new task_10();
                job_x10.enwiki = enwiki;
                job_x2 = new task_2();
                job_x2.testwp = testwp;
                job_x2.enwiki = enwiki;
                job_x4 = new task_4();
                job_x4.enwiki = enwiki;
                job_x4.testwp = testwp;
                job_x6 = new task_6();
                job_x6.enwiki = enwiki;
                job_x1.Init();
                job_x2.Init();
                job_x4.Init();
                started = true; // initialisation is done
            }
        };


        public class Kernel_Main
        {
            public Kernel_Main()
            {
                Start();
            }
            public static void Start()
            {
                PBot Pb = new PBot();

                // Create the thread object, passing in the
                // serverObject.InstanceMethod method using a
                // ThreadStart delegate.
               
                    Pb.Initialise();
                    Thread logger;

                    Pb.t1 = new Thread(new ThreadStart(Pb.d1));
                    Pb.t2 = new Thread(new ThreadStart(Pb.d2));
                    Pb.t4 = new Thread(new ThreadStart(Pb.d4));
                    Pb.t6 = new Thread(new ThreadStart(Pb.d6));
                    Pb.t10 = new Thread(new ThreadStart(Pb.d10));
                    logger = new Thread(new ThreadStart(Logger.start));
                    // Start all tasks
                    //Pb.t1.Start();
                    Pb.t2.Start();
                    Pb.t4.Start();
                    Pb.t6.Start();
                    //Pb.t10.Start();
                    logger.Start();
                    //t.Log("Started");
                


                while (Config.OK == true)
                {
                    Thread.Sleep(3400);
                }
                Pb.t1.Abort();
                Pb.t2.Abort();
                Pb.t4.Abort();
                Pb.t6.Abort();
                t.Log("Aborting, sigterm");
                Thread.Sleep(4000);
                
                logger.Abort();

                // Start the thread.
            }
        };


        static void Main(string[] args)
        {
            Kernel_Main bot = new Kernel_Main();
        }
    }
}
